package com.token;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TokenUtils {
	
	//生成token的ip,用于检验使用和生成token的ip
	public static final String GENERATE_TOKEN_IP = "generateTokenIp";
	//存放token的cookie name
	public static final String TOKEN_NAME = "loginToken";
	//生成token的秘钥
	public static final String KEY = "0a/KrzL2keA26A2PHpi8ARs5N78jwl9YzwPlaXoXt+BwMIEwmNgvFwKE9Bfcvk5P6WZK2i0K/zzVBf6zqqAReg==";
	
	/**
	 * 
	 * @Description: 生成token
	 * @param @param userName:接收令牌的用户
	 * @param @param tel
	 * @param @param expires：过期时间
	 * @param @param claims：自定义参数map集合
	 * @param @return   
	 * @return String  
	 * @throws
	 * @author limh
	 * @date 2017年4月17日
	 */
	public static String generateToken(HttpServletRequest request,HttpServletResponse response,String userName,Date expires, Map<String,Object> claims){
		
		/*ResourceBundle resourceBundle = ResourceBundle.getBundle("token");
		String keyText = resourceBundle.getString("key");
		if (keyText == null) {
        	throw new NullPointerException("keyText can not be null");
        }*/
		
		if (userName == null) {
        	throw new NullPointerException("username can not be null");
        }
        if (expires == null) {
        	throw new NullPointerException("expires can not be null");
        }

        /**
         * key值
         */
        byte[] sikey = null;
		try {
			sikey = new sun.misc.BASE64Decoder().decodeBuffer(TokenUtils.KEY);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        //用签名算法HS256和私钥key生成token
        SignatureAlgorithm signatureAlgorithm =SignatureAlgorithm.HS256;
        JwtBuilder jwtBuilder = Jwts.builder();
        if(claims == null){
        	claims = new HashMap<String,Object>();
        }
        claims.put(TokenUtils.GENERATE_TOKEN_IP, request.getRemoteAddr());//设置ip，用于检验时使用
        jwtBuilder.setClaims(claims);//自定义参数
        jwtBuilder.setIssuer("dahai");//设置发行人
        jwtBuilder.setSubject("org-gateway");//设置抽象主题
        jwtBuilder.setAudience(userName);//to whom the token is intended to be sent
        jwtBuilder.setExpiration(expires);//过期时间
        jwtBuilder.setIssuedAt(new Date());//设置现在时间
        jwtBuilder.setId("v1");//版本v1
        jwtBuilder.signWith(signatureAlgorithm,sikey);
        String token = jwtBuilder.compact();
        //response.addHeader(TokenUtils.TOKEN_NAME, token);
        //设置cookie过期时间和token失效时间一致 TimeUtil.getSecondCa(expires, new Date()).intValue()
        CookiesUtils.setCookie(response, TokenUtils.TOKEN_NAME, token, TimeUtil.getSecondCa(expires, new Date()).intValue(), true);
        return token;
     }
	
	/**
	 * 
	 * @Description: TODO
	 * @param @param request
	 * @param @param response
	 * @param @param token
	 * @param @param checkoutIp:是否检验生成和使用token的ip
	 * @param @return   
	 * @return boolean  
	 * @throws
	 * @author limh
	 * @date 2017年4月21日
	 */
     public static boolean isValid(HttpServletRequest request,HttpServletResponse response, boolean checkoutIp) {
        	String token = CookiesUtils.getCookieValueByName(request, TokenUtils.TOKEN_NAME);
        	if(token == null || "".equals(token)){
        		throw new IllegalArgumentException("登录已过期，请重新登录");
        	}
    		//ResourceBundle resourceBundle = ResourceBundle.getBundle("token");
    		//String keyText = resourceBundle.getString("key");
        	byte[] sikey = null;
			try {
				sikey = new sun.misc.BASE64Decoder().decodeBuffer(TokenUtils.KEY);
			} catch (IOException e) {
				e.printStackTrace();
				throw new IllegalArgumentException("token无效，请先登录");
			}
        	Jws<Claims> claimsJws;
			try {
				claimsJws = Jwts.parser().setSigningKey(sikey).parseClaimsJws(token.trim());
			} catch (ExpiredJwtException e) {
				e.printStackTrace();
				throw new IllegalArgumentException("token已失效，请重新登录");
			} 
        	/*Date expires = claimsJws.getBody().getExpiration();
			if(expires.before(new Date())){
				
			}*/
			if(checkoutIp){
				String currentIp = request.getRemoteAddr();
				String generateTokenIp = (String) claimsJws.getBody().get(TokenUtils.GENERATE_TOKEN_IP);
				if(currentIp == null || "".equals(currentIp)){
					throw new IllegalArgumentException("token无效，请先登录");
				}
				if(!currentIp.equals(generateTokenIp)){
					throw new IllegalArgumentException("token无效，请先登录");
				}
			}
			
            return true;
    }
     
     /**
      * 
      * @Description: token解码
      * @param @param jwsToken
      * @param @param keyText
      * @param @return   
      * @return Claims  
      * @throws
      * @author limh
      * @date 2017年4月18日
      */
     public static Claims decodeToken(HttpServletRequest request,HttpServletResponse response,boolean checkoutIp) {
        if (isValid(request,response,checkoutIp)) {
			try {
				String jwsToken = CookiesUtils.getCookieValueByName(request, TokenUtils.TOKEN_NAME);
				//ResourceBundle resourceBundle = ResourceBundle.getBundle("token");
				//String keyText = resourceBundle.getString("key");
				byte[] sikey = new sun.misc.BASE64Decoder().decodeBuffer(TokenUtils.KEY);
				Jws<Claims> claimsJws = Jwts.parser().setSigningKey(sikey).parseClaimsJws(jwsToken.trim());
	            return claimsJws.getBody();
			} catch (IOException e) {
				e.printStackTrace();
			}
        }
        return null;
    }
    public static void main(String[] args) {
    	/*ResourceBundle resourceBundle = ResourceBundle.getBundle("token");
		String keyText = resourceBundle.getString("key");
	    Date expires = TimeUtil.addSeconds(new Date(), 60); 
	    Map<String,Object> map = new HashMap<String,Object>();
	    map.put("ip","123456");
	    String token=generateToken(keyText,"李明海", expires, map);
	    System.out.println("token:"+token);
	    System.out.println("验签结果"+isValid(token, keyText));
	    System.out.println("用户名"+decodeToken(token, keyText));*/
    }
    
}
